#include "programtabledelegate.h"
#include <QtGui>
#include "syscontroller.h"
//#include "valueeditwnd.h"

ProgramTableDelegate::ProgramTableDelegate(QObject *parent)
	: QItemDelegate(parent),
	  sys_(SysController::instance())
{ }


QWidget *ProgramTableDelegate::createEditor(
							QWidget *parent, 
							const QStyleOptionViewItem &, 
							const QModelIndex &index) const
{
	int item_index = index.column();
	if (item_index >= sys_->itemCount()) {
		return (QWidget *)0;
	}

	// NOTE! : SEEMS THAT I don't have enough knowleage about poly.
	// Here could I use a QWdiget *widget to handle all things, then
	// just return the widget instance ?

	switch (index.row()) {
		case kItemRowNameSuffixCh:
		{
			QComboBox *chCombo = new QComboBox(parent);
			chCombo->addItems(sys_->ChannelList());
			AdjustEditorStyle(chCombo);
			return chCombo;
		}
		case kItemRowBiasRng:
		{
			QComboBox *rngCombo = new QComboBox(parent);
			rngCombo->addItems(sys_->ItemRangeList(item_index, true));
			AdjustEditorStyle(rngCombo);
			return rngCombo;
		}
		case kItemRowBiasVal:
		{
			if (sys_->IsItemRangeInteger(item_index, true)) {
				QSpinBox *biasSpin = new QSpinBox(parent);
				biasSpin->setRange(sys_->ItemRangeLower(item_index, true),
						           sys_->ItemRangeUpper(item_index, true));
				biasSpin->setSingleStep(sys_->ItemRangeStep(item_index, true));
				biasSpin->setAccelerated(true);
				AdjustEditorStyle(biasSpin);
				return biasSpin;
			} else {
				QDoubleSpinBox *biasSpin = new QDoubleSpinBox(parent);
				biasSpin->setRange(sys_->ItemRangeLower(item_index, true),
						           sys_->ItemRangeUpper(item_index, true));
				biasSpin->setSingleStep(sys_->ItemRangeStep(item_index, true));
				biasSpin->setAccelerated(true);
				AdjustEditorStyle(biasSpin);
				return biasSpin;
			}
		}
		case kItemRowWaitTime:
		{
			QDoubleSpinBox *timeSpin = new QDoubleSpinBox(parent);
			timeSpin->setRange(sys_->RangeLower(1), sys_->RangeUpper(1));
			timeSpin->setSingleStep(sys_->RangeStep(1));
			timeSpin->setAccelerated(true);
			AdjustEditorStyle(timeSpin);
			return timeSpin;
		}
		case kItemRowMeasRng:
		{
			QComboBox *rngCombo = new QComboBox(parent);
			rngCombo->addItems(sys_->ItemRangeList(item_index, false));
			AdjustEditorStyle(rngCombo);
			return rngCombo;
		}
		case kItemRowMeasValLower:
		case kItemRowMeasValUpper:
		{
			if (sys_->IsItemRangeInteger(item_index, false)) {
				QSpinBox *measSpin = new QSpinBox(parent);
				measSpin->setRange(sys_->ItemRangeLower(item_index, false),
						           sys_->ItemRangeUpper(item_index, false));
				measSpin->setSingleStep(sys_->ItemRangeStep(item_index, false));
				measSpin->setAccelerated(true);
				AdjustEditorStyle(measSpin);
				return measSpin;
			} else {
				QDoubleSpinBox *measSpin = new QDoubleSpinBox(parent);
				measSpin->setRange(sys_->ItemRangeLower(item_index, false),
						           sys_->ItemRangeUpper(item_index, false));
				measSpin->setSingleStep(sys_->ItemRangeStep(item_index, false));
				measSpin->setAccelerated(true);
				AdjustEditorStyle(measSpin);
				return measSpin;
			}
		}
		case kItemRowFilter:
		{
			QComboBox *filterCombo = new QComboBox(parent);
			filterCombo->addItems(sys_->FilterOptList());
			AdjustEditorStyle(filterCombo);
			return filterCombo;
		}
		case kItemRowVolLimit:
		{
			QDoubleSpinBox *vlimitSpin = new QDoubleSpinBox(parent);
			vlimitSpin->setRange(sys_->RangeLower(2), sys_->RangeUpper(2));
			vlimitSpin->setSingleStep(sys_->RangeStep(2));
			vlimitSpin->setAccelerated(true);
			AdjustEditorStyle(vlimitSpin);
			return vlimitSpin;
		}
		case kItemRowLimitJudge:
		{
			QComboBox *onoffCombo = new QComboBox(parent);
			onoffCombo->addItems(sys_->OnOffList());
			AdjustEditorStyle(onoffCombo);
			return onoffCombo;
		}
		default:
			return (QWidget *)0;
	}
}



void ProgramTableDelegate::setEditorData(
		QWidget *editor, const QModelIndex &index) const
{
	int item_index = index.column();

	switch (index.row()) {
		case kItemRowNameSuffixCh:
		{	
			QComboBox *chCombo = qobject_cast<QComboBox *>(editor);
			chCombo->setCurrentIndex(
					chCombo->findText(sys_->itemChannel(item_index)));
			break;
		}
		case kItemRowBiasRng:
		{
			QComboBox *rngCombo = qobject_cast<QComboBox *>(editor);
			rngCombo->setCurrentIndex(
					rngCombo->findText(sys_->itemBiasRng(item_index)));
			break;
		}
		case kItemRowBiasVal:
		{
			if (sys_->IsItemRangeInteger(item_index, true)) {
				QSpinBox *biasSpin = qobject_cast<QSpinBox *>(editor);
				biasSpin->setValue(sys_->itemBiasVal(item_index).toDouble());
			} else {
				QDoubleSpinBox *biasSpin = 
								qobject_cast<QDoubleSpinBox *>(editor);
				biasSpin->setValue(sys_->itemBiasVal(item_index).toDouble());
			}
			break;
		}
		case kItemRowWaitTime:
		{
			QDoubleSpinBox *timeSpin = qobject_cast<QDoubleSpinBox *>(editor);
			timeSpin->setValue(sys_->itemWaitTime(item_index).toDouble());	
			break;
		}
		case kItemRowMeasRng:
		{
			QComboBox *rngCombo = qobject_cast<QComboBox *>(editor);
			rngCombo->setCurrentIndex(
					rngCombo->findText(sys_->itemMeasRng(item_index)));
			break;
		}
		case kItemRowMeasValLower:
		case kItemRowMeasValUpper:
		{
			bool lower = (kItemRowMeasValLower == index.row());
			if (sys_->IsItemRangeInteger(item_index, false)) {
				QSpinBox *spinBox = qobject_cast<QSpinBox *>(editor);
				spinBox->setValue(
						sys_->itemMeasVal(item_index, lower).toDouble());
			} else {
				QDoubleSpinBox *spinBox = 
						qobject_cast<QDoubleSpinBox *>(editor);
				spinBox->setValue(
						sys_->itemMeasVal(item_index, lower).toDouble());
			}
			break;
		}
		case kItemRowFilter:
		{
			QComboBox *filterCombo = qobject_cast<QComboBox *>(editor);
			filterCombo->setCurrentIndex(
					filterCombo->findText(sys_->itemFilterOpt(item_index)));
			break;
		}
		case kItemRowVolLimit:
		{
			QDoubleSpinBox *vlimitSpin = qobject_cast<QDoubleSpinBox *>(editor);
			vlimitSpin->setValue(sys_->itemVolLimit(item_index).toDouble());	
			break;
		}
		case kItemRowLimitJudge:
		{
			QComboBox *onoffCombo = qobject_cast<QComboBox *>(editor);
			onoffCombo->setCurrentIndex(
					onoffCombo->findText(sys_->itemLimitJudge(item_index)));
			break;
		}
		default:
			break;
	}
}


void ProgramTableDelegate::setModelData(QWidget *editor, 
				QAbstractItemModel *model, const QModelIndex &index) const
{
	switch (index.row()) {
		case kItemRowNameSuffixCh:
		{
			QComboBox *chCombo = qobject_cast<QComboBox *>(editor);
			sys_->setItemChannelEx(index.column(), chCombo->currentText());
			break;
		}
		case kItemRowBiasRng:
		{
			QComboBox *rngCombo = qobject_cast<QComboBox *>(editor);
			sys_->setItemBiasRng(index.column(), rngCombo->currentText());
			break;
		}
		case kItemRowBiasVal:
		{
			if (sys_->IsItemRangeInteger(index.column(), true)) {
				QSpinBox *biasSpin = qobject_cast<QSpinBox *>(editor);
				sys_->setItemBiasVal(index.column(), 
									 QString::number(biasSpin->value()));
			} else {
				QDoubleSpinBox *biasSpin = 
								qobject_cast<QDoubleSpinBox *>(editor);
				sys_->setItemBiasVal(index.column(), 
									 QString::number(biasSpin->value()));
			}
			break;
		}
		case kItemRowWaitTime:
		{
			QDoubleSpinBox *timeSpin = qobject_cast<QDoubleSpinBox *>(editor);
			sys_->setItemWaitTime(index.column(), 
								  QString::number(timeSpin->value()));
			break;
		}
		case kItemRowMeasRng:
		{
			QComboBox *rngCombo = qobject_cast<QComboBox *>(editor);
			sys_->setItemMeasRng(index.column(), rngCombo->currentText());
			break;
		}
		case kItemRowMeasValLower:
		case kItemRowMeasValUpper:
		{
			bool lower = (index.row() == kItemRowMeasValLower);
			if (sys_->IsItemRangeInteger(index.column(), false)) {
				QSpinBox *biasSpin = qobject_cast<QSpinBox *>(editor);
				sys_->setItemMeasVal(index.column(), lower,
									 QString::number(biasSpin->value()));
			} else {
				QDoubleSpinBox *biasSpin = 
								qobject_cast<QDoubleSpinBox *>(editor);
				sys_->setItemMeasVal(index.column(), lower,
									 QString::number(biasSpin->value()));
			}
			break;
		}
		case kItemRowFilter:
		{
			QComboBox *filterCombo = qobject_cast<QComboBox *>(editor);
			sys_->setItemFilterOpt(index.column(), filterCombo->currentText());
			break;
		}
		case kItemRowVolLimit:
		{
			QDoubleSpinBox *vlimitSpin = 
						qobject_cast<QDoubleSpinBox *>(editor);
			sys_->setItemVolLimit(index.column(), 
								  QString::number(vlimitSpin->value()));
			break;
		}
		case kItemRowLimitJudge:
		{
			QComboBox *onoffCombo = qobject_cast<QComboBox *>(editor);
			sys_->setItemLimitJudge(index.column(), onoffCombo->currentText());
			break;
		}
		default:
			break;
	}

	emit itemEditingFinished(index.column());
}


// NOTE:! it's dirty, fix later
void ProgramTableDelegate::AdjustEditorStyle(QWidget *widget) const
{
	widget->setFixedSize(widget->width() * 2, widget->height() * 2);
	widget->setFont(QFont("Fixedsys", 24));
}
